package com.fary.beans.factory.support;

import com.fary.beans.*;
import com.fary.beans.factory.BeanFactory;
import com.fary.beans.factory.BeanFactoryUtils;
import com.fary.beans.factory.FactoryBean;
import com.fary.beans.factory.config.*;
import com.fary.core.DecoratingClassLoader;
import com.fary.core.NamedThreadLocal;
import com.fary.core.ResolvableType;
import com.fary.core.SpringException;
import com.fary.core.convert.ConversionService;
import com.fary.util.*;



import java.beans.PropertyEditor;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    /**
     * Parent bean factory, for bean inheritance support.
     */
    private BeanFactory parentBeanFactory;

    /**
     * ClassLoader to resolve bean class names with, if necessary.
     */
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    /**
     * ClassLoader to temporarily resolve bean class names with, if necessary.
     */
    private ClassLoader tempClassLoader;

    /**
     * Whether to cache bean metadata or rather reobtain it for every access.
     */
    private boolean cacheBeanMetadata = true;

    /**
     * Resolution strategy for expressions in bean definition values.
     */
    private BeanExpressionResolver beanExpressionResolver;

    /**
     * Spring ConversionService to use instead of PropertyEditors.
     */
    private ConversionService conversionService;

    /**
     * Custom PropertyEditorRegistrars to apply to the beans of this factory.
     */
    private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);

    /**
     * Custom PropertyEditors to apply to the beans of this factory.
     */
    private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);

    /**
     * A custom TypeConverter to use, overriding the default PropertyEditor mechanism.
     */
    private TypeConverter typeConverter;

    /**
     * String resolvers to apply e.g. to annotation attribute values.
     */
    private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();

    /**
     * BeanPostProcessors to apply in createBean.
     */
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

    /**
     * Indicates whether any InstantiationAwareBeanPostProcessors have been registered.
     */
    private volatile boolean hasInstantiationAwareBeanPostProcessors;

    /**
     * Indicates whether any DestructionAwareBeanPostProcessors have been registered.
     */
    private volatile boolean hasDestructionAwareBeanPostProcessors;

    /**
     * Map from scope identifier String to corresponding Scope.
     */
    private final Map<String, Scope> scopes = new LinkedHashMap<>(8);

    /** Security context used when running with a SecurityManager. */
//    private SecurityContextProvider securityContextProvider;

    /**
     * Map from bean name to merged RootBeanDefinition.
     */
    private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

    /**
     * Names of beans that have already been created at least once.
     */
    private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

    /**
     * Names of beans that are currently in creation.
     */
    private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation");

    public AbstractBeanFactory() {
    }

    @Override
    public boolean isActuallyInCreation(String beanName) {
        return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName));
    }

    /**
     * 判断多例是否正在创建中
     */
    protected boolean isPrototypeCurrentlyInCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        return curVal != null && (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)));
    }

    protected boolean hasDestructionAwareBeanPostProcessors() {
        return this.hasDestructionAwareBeanPostProcessors;
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // 1.如果beanPostProcessor已经存在则移除（可以起到排序的效果，beanPostProcessor可能本来在前面，移除再添加，则变到最后面）
        this.beanPostProcessors.remove(beanPostProcessor);
        // 3.如果beanPostProcessor是InstantiationAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过InstantiationAwareBeanPostProcessors
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        // 4.如果beanPostProcessor是DestructionAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过DestructionAwareBeanPostProcessor
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
        // 2.将beanPostProcessor添加到beanPostProcessors缓存
        this.beanPostProcessors.add(beanPostProcessor);
    }

    /**
     * beanName转换，这里主要有两方面的考虑：
     * 1:如果beanName是以&开头的，则表明是要返回FactoryBean本身
     * 而不是其生产出来的对象，而FactoryBean存储的时候，跟普通的bean一样
     * 2:如果传入的是别名，则是需要转换为实际的beanName的
     */
    protected String transformedBeanName(String name) {
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

    /**
     * 获取原始beanName名称
     */
    protected String originalBeanName(String name) {
        String beanName = transformedBeanName(name);
        if (name.startsWith(FACTORY_BEAN_PREFIX)) {
            beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        return beanName;
    }

    @Override
    public void setParentBeanFactory(BeanFactory parentBeanFactory) {
        if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
            throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
        }
        this.parentBeanFactory = parentBeanFactory;
    }

    @Override
    public BeanFactory getParentBeanFactory() {
        return this.parentBeanFactory;
    }


    protected boolean hasBeanCreationStarted() {
        return !this.alreadyCreated.isEmpty();
    }


    public List<BeanPostProcessor> getBeanPostProcessors() {
        return this.beanPostProcessors;
    }

    @Override
    public boolean isCacheBeanMetadata() {
        return this.cacheBeanMetadata;
    }

    protected void cleanupAfterBeanCreationFailure(String beanName) {
        synchronized (this.mergedBeanDefinitions) {
            this.alreadyCreated.remove(beanName);
        }
    }

    /**
     * 清除合并缓存让BeanDefinition可以重新合并
     */
    protected void clearMergedBeanDefinition(String beanName) {
        this.mergedBeanDefinitions.remove(beanName);
    }

    public void clearMetadataCache() {
        this.mergedBeanDefinitions.keySet().removeIf(bean -> !isBeanEligibleForMetadataCaching(bean));
    }

    protected boolean isBeanEligibleForMetadataCaching(String beanName) {
        return this.alreadyCreated.contains(beanName);
    }

    /**
     * 获取bean对象
     */
    @Override
    public Object getBean(String name) throws SpringException {
        return doGetBean(name, null, null, false);
    }

    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws SpringException {

        // 1.解析beanName，主要是解析别名、去掉FactoryBean的前缀“&”
        final String beanName = transformedBeanName(name);
        Object bean;
        // 2.尝试从缓存中获取beanName对应的实例
        Object sharedInstance = getSingleton(beanName);
        // 3. 获取bean实例
        if (sharedInstance != null && args == null) {
            // 3.如果beanName的实例存在于缓存中
            // 3.1 返回beanName对应的实例对象（主要用于FactoryBean的特殊处理，普通Bean会直接返回sharedInstance本身）
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
            // 多例循环依赖直接报错（spring无法解决多例循环依赖）
            // 4.scope为prototype的循环依赖校验：如果beanName已经正在创建Bean实例中，而此时我们又要再一次创建beanName的实例，则代表出现了循环依赖，需要抛出异常。
            // 例子：如果存在A中有B的属性，B中有A的属性，那么当依赖注入的时候，就会产生当A还未创建完的时候因为对于B的创建再次返回创建A，造成循环依赖
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new SpringException(beanName + " Requested bean is currently in creation: Is there an unresolvable circular reference?");
            }

            // 5.获取parentBeanFactory
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 5.1 如果parentBeanFactory存在，并且beanName在当前BeanFactory不存在Bean定义，则尝试从parentBeanFactory中获取bean实例
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 5.2 将别名解析成真正的beanName
                String nameToLookup = originalBeanName(name);
                // 5.3 尝试在parentBeanFactory中获取bean对象实例
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                } else if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                } else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            // 如果创建bean不是为了类型检查，则要标记当前bean已经被创建或者即将被创建
            // 以便于BeanFactory可以优化重复创建的bean的缓存
            // 6.如果不是仅仅做类型检测，而是创建bean实例，这里要将beanName放到alreadyCreated缓存
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // 7.根据beanName重新获取MergedBeanDefinition（步骤6将MergedBeanDefinition删除了，这边获取一个新的）
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 7.1 检查MergedBeanDefinition，如果是抽象的就抛出异常
                checkMergedBeanDefinition(mbd, beanName, args);
                // 8.拿到当前bean依赖的bean名称集合，在实例化自己之前，需要先实例化自己依赖的bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 8.1 遍历当前bean依赖的bean名称集合
                    for (String dep : dependsOn) {
                        // 8.2 检查dep是否依赖于beanName，即检查是否存在循环依赖
                        if (isDependent(beanName, dep)) {
                            throw new SpringException("Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 8.4 将dep和beanName的依赖关系注册到缓存中，A->B 则注册B->A到dependentBeanMap集合
                        registerDependentBean(dep, beanName);
                        try {
                            // 8.5 获取dep对应的bean实例，如果dep还没有创建bean实例，则创建dep的bean实例
                            getBean(dep);
                        } catch (SpringException ex) {
                            throw new SpringException("'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 9.针对不同的scope进行bean的创建
                if (mbd.isSingleton()) {
                    // 9.1 scope为singleton的bean创建（新建了一个ObjectFactory，并且重写了getObject方法）
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 9.1.1 创建Bean实例
                            return createBean(beanName, mbd, args);
                        } catch (SpringException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    // 9.1.2 返回beanName对应的实例对象
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    // 9.2 scope为prototype的bean创建
                    Object prototypeInstance = null;
                    try {
                        // 9.2.1 创建实例前的操作（将beanName保存到prototypesCurrentlyInCreation缓存中）
                        beforePrototypeCreation(beanName);
                        // 9.2.2 创建Bean实例
                        prototypeInstance = createBean(beanName, mbd, args);
                    } finally {
                        // 9.2.3 创建实例后的操作（将创建完的beanName从prototypesCurrentlyInCreation缓存中移除）
                        afterPrototypeCreation(beanName);
                    }
                    // 9.2.4 返回beanName对应的实例对象
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    // 9.3 其他scope的bean创建，可能是request之类的
                    // 9.3.1 根据scopeName，从缓存拿到scope实例
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        // 9.3.2 其他scope的bean创建（新建了一个ObjectFactory，并且重写了getObject方法）
                        Object scopedInstance = scope.get(beanName, () -> {
                            // 9.3.3 创建实例前的操作（将beanName保存到prototypesCurrentlyInCreation缓存中）
                            beforePrototypeCreation(beanName);
                            try {
                                // 9.3.4 创建bean实例
                                return createBean(beanName, mbd, args);
                            } finally {
                                // 9.3.5 创建实例后的操作（将创建完的beanName从prototypesCurrentlyInCreation缓存中移除）
                                afterPrototypeCreation(beanName);
                            }
                        });
                        // 9.3.6 返回beanName对应的实例对象
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException ex) {
                        throw new SpringException(beanName + " Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex);
                    }
                }
            } catch (SpringException ex) {
                // 如果创建bean实例过程中出现异常，则将beanName从alreadyCreated缓存中移除
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        // 10.检查所需类型是否与实际的bean对象的类型匹配
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                // 10.1 类型不对，则尝试转换bean类型
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new SpringException("类型转换错误");
                }
                return convertedBean;
            } catch (SpringException ex) {
                throw new SpringException("类型转换错误");
            }
        }
        // 11.返回创建出来的bean实例对象
        return (T) bean;
    }

    /**
     * 获取给定bean实例的对象，或者实例本身或FactoryBean中创建的对象。
     */
    protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
        // 1.如果name以“&”为前缀，但是beanInstance不是FactoryBean，则抛异常
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new SpringException(transformedBeanName(name) + " Bean Is Not A Factory");
            }
        }
        // 2.1 如果beanInstance不是FactoryBean（也就是普通bean），则直接返回beanInstance
        // 2.2 如果beanInstance是FactoryBean，并且name以“&”为前缀，则直接返回beanInstance（以“&”为前缀代表想获取的是FactoryBean本身）
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }
        // 3.走到这边，代表beanInstance是FactoryBean，但name不带有“&”前缀，表示想要获取的是FactoryBean创建的对象实例
        Object object = null;
        if (mbd == null) {
            // 4.如果mbd为空，则尝试从factoryBeanObjectCache缓存中获取该FactoryBean创建的对象实例
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // 5.只有beanInstance是FactoryBean才能走到这边，因此直接强转
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // 检测这个bean是否已经被加载过
            if (mbd == null && containsBeanDefinition(beanName)) {
                //进行父类和子类的合并，把存储xml配置的GenericBeanDefinition转换为RootBeanDefinition
                // 6.mbd为空，但是该bean的BeanDefinition在缓存中存在，则获取该bean的MergedBeanDefinition
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            // 7.mbd是否是合成的（这个字段比较复杂，mbd正常情况都不是合成的，也就是false，有兴趣的可以自己查阅资料看看）
            // 是否是用户自定义的beanDefinition(默认是false)
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 通过工厂FactoryBean获取
            // 8.从FactoryBean获取对象实例
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

    /**
     * 标记当前bean已经创建了
     * 在创建bean期间有可能有一些元数据的变化，这里清除合并缓存让BeanDefinition可以重新合并
     */
    protected void markBeanAsCreated(String beanName) {
        // 1.如果alreadyCreated缓存中不包含beanName
        if (!this.alreadyCreated.contains(beanName)) {
            synchronized (this.mergedBeanDefinitions) {
                if (!this.alreadyCreated.contains(beanName)) {
                    // 2.将beanName的MergedBeanDefinition从mergedBeanDefinitions缓存中移除，
                    // 在之后重新获取MergedBeanDefinition，避免BeanDefinition在创建过程中发生变化
                    clearMergedBeanDefinition(beanName);
                    // 3.将beanName添加到alreadyCreated缓存中，代表该beanName的bean实例已经创建（或即将创建）
                    this.alreadyCreated.add(beanName);
                }
            }
        }
    }

    /**
     * 获取合并BeanDefinition
     */
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws SpringException {
        // 从 bean名称映射到合并的RootBeanDefinition的集合 中获取beanName对应的RootBeanDefinition
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        // 如果mbd不为null 且 不需要重新合并定义
        if (mbd != null) {
            return mbd;
        }
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }

    @Override
    public BeanDefinition getMergedBeanDefinition(String name) throws SpringException {
        String beanName = transformedBeanName(name);
        // Efficiently check whether bean definition exists in this factory.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
        }
        // Resolve merged bean definition locally.
        return getMergedLocalBeanDefinition(beanName);
    }

    /**
     * 获取合并BeanDefinition
     */
    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) throws SpringException {
        return getMergedBeanDefinition(beanName, bd, null);
    }

    /**
     * 获取合并BeanDefinition
     */
    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, BeanDefinition containingBd) throws SpringException {
        // 同步： 使用 从bean名称映射到合并的RootBeanDefinition集合 进行加锁
        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;

            // Check with full lock now in order to enforce the same merged instance.
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }

            if (mbd == null) {
                // 如果没有指定parent，则直接复制到RootBeanDefinition
                if (bd.getParentName() == null) {
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    } else {
                        mbd = new RootBeanDefinition(bd);
                    }
                } else {
                    // bd是一个ChildBeanDefinition的情况,需要将bd和其parent bean definition 合并到一起
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                            pbd = getMergedBeanDefinition(parentBeanName);
                        } else {
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            } else {
                                throw new SpringException("Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without an AbstractBeanFactory parent");
                            }
                        }
                    } catch (SpringException ex) {
                        throw new SpringException(beanName + " Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // Deep copy with overridden values.
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }

                // 如果没有配置scope，则默认为singleton
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
                }

                // 非单例bean里面只能是非单例bean（跟外面bean的scope一致）
                // 这里就是更正这个问题里面的scope状态
                //如果当前bean为被包含bean，它的scope是单例的而其包含bean的scope不是单例的，那么继承包含bean的scope
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                // 缓存合并的bean定义
                //（以后可能会重新合并，以获取元数据更改）
                // 如果当前bean不是被包含的bean，那么进行缓存
                // 为什么不缓存被包含bean呢？被包含bean换句话，就是别人的属性，属性可能会发生改变
                if (containingBd == null && isCacheBeanMetadata()) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            return mbd;
        }
    }

    /**
     * 解析beanClass，获取bean对应的class对象
     */
    protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch) throws SpringException {
        try {
            if (mbd.hasBeanClass()) {
                return mbd.getBeanClass();
            }
            return doResolveBeanClass(mbd, typesToMatch);
        } catch (ClassNotFoundException ex) {
            throw new SpringException(mbd.getBeanClassName(), ex);
        }
    }

    /**
     * 解析beanClass，获取bean对应的class对象
     */
    private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {

        ClassLoader beanClassLoader = getBeanClassLoader();
        ClassLoader dynamicLoader = beanClassLoader;
        boolean freshResolve = false;

        // 类型匹配
        if (!ObjectUtils.isEmpty(typesToMatch)) {
            ClassLoader tempClassLoader = getTempClassLoader();
            if (tempClassLoader != null) {
                dynamicLoader = tempClassLoader;
                freshResolve = true;
                if (tempClassLoader instanceof DecoratingClassLoader) {
                    DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                    for (Class<?> typeToMatch : typesToMatch) {
                        dcl.excludeClass(typeToMatch.getName());
                    }
                }
            }
        }

        String className = mbd.getBeanClassName();
        if (className != null) {
            Object evaluated = evaluateBeanDefinitionString(className, mbd);
            if (!className.equals(evaluated)) {
                // A dynamically resolved expression, supported as of 4.2...
                if (evaluated instanceof Class) {
                    return (Class<?>) evaluated;
                } else if (evaluated instanceof String) {
                    className = (String) evaluated;
                    freshResolve = true;
                } else {
                    throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                }
            }
            // SPEL表达式
            if (freshResolve) {
                if (dynamicLoader != null) {
                    try {
                        return dynamicLoader.loadClass(className);
                    } catch (ClassNotFoundException ex) {

                    }
                }
                return ClassUtils.forName(className, dynamicLoader);
            }
        }
        return mbd.resolveBeanClass(beanClassLoader);
    }

    protected void beforePrototypeCreation(String beanName) {
        // 1.拿到当前线程中正在创建的prototype的bean的beanName集合
        Object curVal = this.prototypesCurrentlyInCreation.get();
        // 2.如果为空，则将ThreadLocal设置成当前的beanName
        if (curVal == null) {
            this.prototypesCurrentlyInCreation.set(beanName);
        } else if (curVal instanceof String) {
            // 3.如果不为空，并且是String类型，则代表目前只有一个beanName，将之前和当前的一起封装成Set<String>，设置到ThreadLocal中
            Set<String> beanNameSet = new HashSet<>(2);
            beanNameSet.add((String) curVal);
            beanNameSet.add(beanName);
            this.prototypesCurrentlyInCreation.set(beanNameSet);
        } else {
            // 4.如果不为空，并且不是String，则必然是Set<String>类型，将当前的beanName加到Set中去
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.add(beanName);
        }
    }

    protected void afterPrototypeCreation(String beanName) {
        // 1.拿到当前线程中正在创建的prototype的bean的beanName集合
        Object curVal = this.prototypesCurrentlyInCreation.get();
        // 2.如果是String类型，则代表目前只有一个beanName，则直接移除
        if (curVal instanceof String) {
            this.prototypesCurrentlyInCreation.remove();
        } else if (curVal instanceof Set) {
            // 3.如果是Set类型，则从Set从移除beanName
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.remove(beanName);
            if (beanNameSet.isEmpty()) {
                this.prototypesCurrentlyInCreation.remove();
            }
        }
    }


    public boolean isBeanNameInUse(String beanName) {
        return false;
    }

    @Override
    public boolean containsLocalBean(String name) {
        String beanName = transformedBeanName(name);
        return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
                (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
    }


    @Override
    public boolean isFactoryBean(String name) throws SpringException {
        String beanName = transformedBeanName(name);
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            return (beanInstance instanceof FactoryBean);
        }
        // No singleton instance found -> check bean definition.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    }

    /**
     * 检查给定的合并后mbd，不合格会引发验证异常：
     */
    protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args) throws SpringException {
        // 如果是抽象的，则抛出异常
        if (mbd.isAbstract()) {
            throw new SpringException(beanName);
        }
    }

    /**
     * SPEL语言-Spring Expression Language解析
     */
    protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {
        // 没有SPEL表达式解析器，直接返回
        if (this.beanExpressionResolver == null) {
            return value;
        }
        Scope scope = null;
        if (beanDefinition != null) {
            String scopeName = beanDefinition.getScope();
            if (scopeName != null) {
                scope = getRegisteredScope(scopeName);
            }
        }
        return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
    }

    protected void initBeanWrapper(BeanWrapper bw) {
        bw.setConversionService(getConversionService());
        registerCustomEditors(bw);
    }

    protected void registerCustomEditors(PropertyEditorRegistry registry) {
        PropertyEditorRegistrySupport registrySupport = (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
        if (registrySupport != null) {
            registrySupport.useConfigValueEditors();
        }
        if (!this.propertyEditorRegistrars.isEmpty()) {
            for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
                registrar.registerCustomEditors(registry);
            }
        }
        if (!this.customEditors.isEmpty()) {
            this.customEditors.forEach((requiredType, editorClass) -> registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
        }
    }

    @Override
    public void setConversionService(ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    @Override
    public ConversionService getConversionService() {
        return this.conversionService;
    }

    protected TypeConverter getCustomTypeConverter() {
        return this.typeConverter;
    }

    @Override
    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    public ClassLoader getTempClassLoader() {
        return this.tempClassLoader;
    }

    @Override
    public Scope getRegisteredScope(String scopeName) {
        Assert.notNull(scopeName, "Scope identifier must not be null");
        return this.scopes.get(scopeName);
    }

    protected boolean hasInstantiationAwareBeanPostProcessors() {
        return this.hasInstantiationAwareBeanPostProcessors;
    }

    @Override
    public boolean containsBean(String name) {
        String beanName = transformedBeanName(name);
        if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
            return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
        }
        // Not found -> check parent.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
    }

    @Override
    public String resolveEmbeddedValue(String value) {
        if (value == null) {
            return null;
        }
        String result = value;
        for (StringValueResolver resolver : this.embeddedValueResolvers) {
            result = resolver.resolveStringValue(result);
            if (result == null) {
                return null;
            }
        }
        return result;
    }

    @Override
    public TypeConverter getTypeConverter() {
        TypeConverter customConverter = getCustomTypeConverter();
        if (customConverter != null) {
            return customConverter;
        } else {
            // Build default TypeConverter, registering custom editors.
            SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            typeConverter.setConversionService(getConversionService());
            registerCustomEditors(typeConverter);
            return typeConverter;
        }
    }

    protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
        if (!this.alreadyCreated.contains(beanName)) {
            removeSingleton(beanName);
            return true;
        } else {
            return false;
        }
    }

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        // 1.mbd的scope不是prototype && 给定的bean需要在关闭时销毁
        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
            if (mbd.isSingleton()) {
                // 2.单例模式下注册用于销毁的bean到disposableBeans缓存，执行给定bean的所有销毁工作：
                // DestructionAwareBeanPostProcessors，DisposableBean接口，自定义销毁方法
                // 2.1 DisposableBeanAdapter：使用DisposableBeanAdapter来封装用于销毁的bean
                registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
            } else {
                // 3.自定义scope处理
                // A bean with a custom scope...
                Scope scope = this.scopes.get(mbd.getScope());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                }
                scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
            }
        }
    }

    protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
        // 1.DisposableBeanAdapter.hasDestroyMethod(bean, mbd)：判断bean是否有destroy方法
        // 2.hasDestructionAwareBeanPostProcessors()：判断当前BeanFactory是否注册过DestructionAwareBeanPostProcessor
        // 3.DisposableBeanAdapter.hasApplicableProcessors：是否存在适用于bean的DestructionAwareBeanPostProcessor
        return (bean.getClass() != NullBean.class &&
                (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
                        DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
    }

    @Override
    public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws SpringException {
        String beanName = transformedBeanName(name);

        // Check manually registered singletons.
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
            if (beanInstance instanceof FactoryBean) {
                if (!BeanFactoryUtils.isFactoryDereference(name)) {
                    Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
                    return (type != null && typeToMatch.isAssignableFrom(type));
                } else {
                    return typeToMatch.isInstance(beanInstance);
                }
            } else if (!BeanFactoryUtils.isFactoryDereference(name)) {
                if (typeToMatch.isInstance(beanInstance)) {
                    // Direct match for exposed instance?
                    return true;
                } else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
                    // Generics potentially only match on the target class, not on the proxy...
                    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    Class<?> targetType = mbd.getTargetType();
                    if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
                        // Check raw class match as well, making sure it's exposed on the proxy.
                        Class<?> classToMatch = typeToMatch.resolve();
                        if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
                            return false;
                        }
                        if (typeToMatch.isAssignableFrom(targetType)) {
                            return true;
                        }
                    }
                    ResolvableType resolvableType = mbd.targetType;
                    if (resolvableType == null) {
                        resolvableType = mbd.factoryMethodReturnType;
                    }
                    return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
                }
            }
            return false;
        } else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
            // null instance registered
            return false;
        }

        // No singleton instance found -> check bean definition.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // No bean definition found in this factory -> delegate to parent.
            return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);
        }

        // Retrieve corresponding bean definition.
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

        Class<?> classToMatch = typeToMatch.resolve();
        if (classToMatch == null) {
            classToMatch = FactoryBean.class;
        }
        Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ? new Class<?>[]{classToMatch} : new Class<?>[]{FactoryBean.class, classToMatch});

        // Check decorated bean definition, if any: We assume it'll be easier
        // to determine the decorated bean's type than the proxy's type.
        BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
        if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
            RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
            Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
            if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
                return typeToMatch.isAssignableFrom(targetClass);
            }
        }

        Class<?> beanType = predictBeanType(beanName, mbd, typesToMatch);
        if (beanType == null) {
            return false;
        }

        // Check bean class whether we're dealing with a FactoryBean.
        if (FactoryBean.class.isAssignableFrom(beanType)) {
            if (!BeanFactoryUtils.isFactoryDereference(name) && beanInstance == null) {
                // If it's a FactoryBean, we want to look at what it creates, not the factory class.
                beanType = getTypeForFactoryBean(beanName, mbd);
                if (beanType == null) {
                    return false;
                }
            }
        } else if (BeanFactoryUtils.isFactoryDereference(name)) {
            // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
            // type but we nevertheless are being asked to dereference a FactoryBean...
            // Let's check the original bean class and proceed with it if it is a FactoryBean.
            beanType = predictBeanType(beanName, mbd, FactoryBean.class);
            if (beanType == null || !FactoryBean.class.isAssignableFrom(beanType)) {
                return false;
            }
        }

        ResolvableType resolvableType = mbd.targetType;
        if (resolvableType == null) {
            resolvableType = mbd.factoryMethodReturnType;
        }
        if (resolvableType != null && resolvableType.resolve() == beanType) {
            return typeToMatch.isAssignableFrom(resolvableType);
        }
        return typeToMatch.isAssignableFrom(beanType);
    }

    protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        Class<?> targetType = mbd.getTargetType();
        if (targetType != null) {
            return targetType;
        }
        if (mbd.getFactoryMethodName() != null) {
            return null;
        }
        return resolveBeanClass(mbd, beanName, typesToMatch);
    }

    protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
        if (!mbd.isSingleton()) {
            return null;
        }
        try {
            FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
            return getTypeForFactoryBean(factoryBean);
        } catch (SpringException ex) {
            return null;
        }
    }

    @Override
    public boolean isTypeMatch(String name, Class<?> typeToMatch) throws SpringException {
        return isTypeMatch(name, ResolvableType.forRawClass(typeToMatch));
    }


    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
        // 判断当前bean类型
        Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
        return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
    }

    @Override
    public boolean isSingleton(String name) throws SpringException {
        String beanName = transformedBeanName(name);

        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            if (beanInstance instanceof FactoryBean) {
                return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton());
            } else {
                return !BeanFactoryUtils.isFactoryDereference(name);
            }
        }

        // No singleton instance found -> check bean definition.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // No bean definition found in this factory -> delegate to parent.
            return parentBeanFactory.isSingleton(originalBeanName(name));
        }

        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

        // In case of FactoryBean, return singleton status of created object if not a dereference.
        if (mbd.isSingleton()) {
            if (isFactoryBean(beanName, mbd)) {
                if (BeanFactoryUtils.isFactoryDereference(name)) {
                    return true;
                }
                FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                return factoryBean.isSingleton();
            } else {
                return !BeanFactoryUtils.isFactoryDereference(name);
            }
        } else {
            return false;
        }
    }


    /**
     * 是否包含指定BeanDefinition
     */
    protected abstract boolean containsBeanDefinition(String beanName);

    protected abstract BeanDefinition getBeanDefinition(String beanName) throws SpringException;

    protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws SpringException;
}